#include "lighting.fx"

cbuffer cbPerFrame
{
	Light gLight;
	float3 gEyePosW;
};

cbuffer cbPerObject
{
	float4x4 gWorld;
	float4x4 gWVP;
	float4x4 gTexMtx;
	float4 gReflectMtrl;
	bool gCubeMapEnabled;
};

Texture2D	gDiffuseMap;
Texture2D	gSpecMap;
TextureCube gCubeMap;

SamplerState gTriLinearSampler
{
	Filter = MIN_MAG_MIP_LINEAR;
	AddressU = Wrap;
	AddressV = Wrap;
};

struct VS_IN
{
	float3 posL		: POSITION;
	float3 normalL	: NORMAL;
	float2 texC		: TEXCOORD;
};

struct VS_OUT
{
	float4 posH		: SV_POSITION;
	float3 posW		: POSITION;
	float3 normalW	: NORMAL;
	float2 texC0	: TEXCOORD0;
	float2 texC1	: TEXCOORD1;
};

VS_OUT VS(VS_IN vIn)
{
	VS_OUT vOut;
	
	// transform to world space
	vOut.posW	 = mul(float4(vIn.posL, 1.0f), gWorld);
	vOut.normalW = mul(float4(vIn.normalL, 0.0f), gWorld);
	
	// transform to homogeneous clip space
	vOut.posH	 = mul(float4(vIn.posL, 1.0f), gWVP);
	
	// vertex attributes
	vOut.texC0	 = vIn.texC;
	vOut.texC1	 = mul(float4(vIn.texC, 0.0f, 1.0f), gTexMtx);
	
	return vOut;
}

float reflectance(float3 reflW, float3 normalW)
{
	float refl0 = 0.0532544f;
	float oneSubCos = 1.0f - dot(reflW, normalW);
	float oneSubCos2 = oneSubCos * oneSubCos;
	float oneSubCos5 = oneSubCos * oneSubCos2 * oneSubCos2;
	float reflK = refl0 + (1.0f - refl0) * oneSubCos5;
	//return clamp(refK, 0.0f, 1.0f);
	return reflK;
}

float4 PS(VS_OUT pIn) : SV_Target
{	
	// texture map to materials
	//float  alpha	= gDiffuseMap.Sample( gTriLinearSampler,  pIn.texC0 ).a;
	float alpha = 1.0f;
	//clip(alpha - 0.1f);
	float4 diffuse	= gDiffuseMap.Sample( gTriLinearSampler,  pIn.texC1 );
	float4 spec = gSpecMap.Sample( gTriLinearSampler, pIn.texC1 );
	
	// specular power map from float to byte
	spec.a *= 256.0f;
	
	// normalize interpolated vector
	float3 normalW = normalize(pIn.normalW);
	
	// computer lit color
	Surface surface = {pIn.posW, normalW, diffuse, spec};
	float3 litColor = ParallelLight(surface, gLight, gEyePosW) * alpha;
	//float3 litColor = float3(0.0f, 0.0f, 0.0f);
	
	[branch]
	if ( gCubeMapEnabled )
	{
		// reflection
		float3 incident = normalize(pIn.posW - gEyePosW);
		float3 reflW =reflect(incident, normalW);
		float reflK = reflectance(reflW, normalW);
		float4 reflectedColor = gCubeMap.Sample(gTriLinearSampler, reflW);
		//litColor += (gReflectMtrl * reflectedColor).rgb;
		litColor += (reflK * reflectedColor).rgb;
		
		// refraction
		float refrK = 1.0f - reflK;
		float etaRatio = 0.7692f;
		float3 refrW = refract(incident, normalW, etaRatio);
		float4 refractedColor = gCubeMap.Sample(gTriLinearSampler, refrW);
		litColor += (refrK * refractedColor).rgb;
		alpha = 1.0f;
	}
	
	return float4(litColor, alpha);
}

technique10 WaveTech
{
	pass P0
	{
		SetVertexShader( CompileShader(vs_4_0, VS()) );
		SetGeometryShader( NULL );
		SetPixelShader( CompileShader(ps_4_0, PS()) );
	}
}
